/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fallen.deck.hibernate;

import fallen.deck.Drecker;
import fallen.deck.entity.*;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;

/**
 *
 * @author MotorolaUTN
 */
public class Queries {

    /****** GETTERS ******/
    
    public static List getDemons(String pathway, String expansion) {
        List demons = null;
        try {
            Supertype[] demon = {getSupertype("Demonio")};
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();

            Query query = session.createQuery("select distinct c "
                    + " from Card c, Pathway p, Expansion e, Supertype s"
                    + " where c.pathway.name = ?"
                    + " and c.expansion.name = ?"
                    + " and :demon in elements (c.supertype)"
                    + " order by c.number");
            query.setParameter(0, pathway);
            query.setParameter(1, expansion);
            query.setParameterList("demon", demon);
            demons = query.list();
            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return demons;
    }

    public static List getDemons(String pathway) {
        List demons = null;
        try {
            Supertype[] demon = {getSupertype("Demonio")};
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();

            Query query = session.createQuery("select distinct c "
                    + " from Card c"
                    + " where c.pathway.name = ?"
                    + " and :demon in elements (c.supertype)");
            query.setParameter(0, pathway);
            query.setParameterList("demon", demon);
            demons = query.list();
            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return demons;
    }

    public static Deck getDeck (long id)
    {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
        Deck deck = (Deck)session.get(Deck.class, id);
        Drecker.inform("Loaded " + deck.getDemon().getPathway().getName()
                + " Deck: " + deck.getName() + " with "
                + deck.getCards().size() + " cards.");
        session.getTransaction().commit();
        return deck;
    }
    
    public static List getDecks() {
        return getObjectsFromClass("Deck");
    }

    public static List getCards(Expansion exp, Pathway path, Type type){
        String expansion=(exp!=null)?exp.getName():"Despertar";
        String pathway=(path!=null)?path.getName():"Neutral";
        String typ=(type!=null)?type.getName():"Aliado";
        return getCards(expansion, pathway, typ);
    }

    public static List getCards(String exp, String path, String type) {
        List cards = null;
        try {
            Type[] oType = {getType(type)};
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();

            Query query = session.createQuery("select distinct c "
                    + " from Card c, Pathway p, Expansion e, Type t"
                    + " where c.pathway.name = ?"
                    + " and c.expansion.name = ?"
                    + " and :type in elements (c.type)"
                    + " order by c.number");
            query.setParameter(0, path);
            query.setParameter(1, exp);
            query.setParameterList("type", oType);
            cards = query.list();
            session.getTransaction().commit();
        } catch (HibernateException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cards;
    }

    public static List getCards() {
        return getObjectsFromClass("Card");
    }

    public static List getExpansions() {
        return getObjectsFromClass("Expansion");
    }

    public static List getSupertypes() {
        return getObjectsFromClass("Supertype");
    }

    public static List getTypes() {
        return getObjectsFromClass("Type");
    }

    public static List getSubtypes() {
        return getObjectsFromClass("Subtype");
    }

    public static List getArtists() {
        return getObjectsFromClass("Artist");
    }

    public static List getPathways() {
        return getObjectsFromClass("Pathway");
    }

    public static List getFrequencies() {
        return getObjectsFromClass("Frequency");
    }

    private static List getObjectsFromClass(String className) {
        return executeQuery("from " + className);
    }

    public static Pathway getPathway(String name) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Query query = session.createQuery("select p"
                + " from Pathway p "
                + " where p.name = ?");
        query.setParameter(0, name);
        Pathway pathway = (Pathway) query.uniqueResult();
        session.getTransaction().commit();
        return pathway;
    }

    public static Card getCard(Expansion exp, int number)
    {
        return getCard(exp.getName(), number);
    }

    public static Card getCard(String exp, int number) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Query query = session.createQuery("select c"
                + " from Card c, Expansion e "
                + " where c.expansion = e"
                + " and e.name = :exp"
                + " and c.number = :num");
        query.setParameter("exp", exp);
        query.setParameter("num", number);
        Card card = (Card) query.uniqueResult();
        session.getTransaction().commit();
        return card;
    }

    public static Supertype getSupertype(String name) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Query query = session.createQuery("select s"
                + " from Supertype s "
                + " where s.name = ?");
        query.setParameter(0, name);
        Supertype supertype = (Supertype) query.uniqueResult();
        session.getTransaction().commit();
        return supertype;
    }

    public static Type getType(String name) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Query query = session.createQuery("select t"
                + " from Type t "
                + " where t.name = ?");
        query.setParameter(0, name);
        Type type = (Type) query.uniqueResult();
        session.getTransaction().commit();
        return type;
    }
    
    /****** REMOVE ******/
    
    public static void remove(Card card) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        session.delete(card);
        session.getTransaction().commit();
    }
    
    public static void remove(Deck deck) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        session.delete(deck);
        session.getTransaction().commit();
    }

    /****** SAVE ******/
    
    /**
     * Checks if there is any deck with the same 'name' saved on the data base.
     * @param name to check
     * @return True if the name is available for a new Deck.
     */
    public static boolean checkName(String name)
    {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        Query query = session.createQuery("select d"
                + " from Deck d"
                + " where d.name = :name");
        query.setParameter("name", name);
        boolean isAvailable = query.list().isEmpty();
        session.getTransaction().commit();
        return isAvailable;
    }
    
    public static boolean save(Deck d) {
        boolean result = true;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();

            session.saveOrUpdate(d);

            session.flush();

            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }
    
    public static boolean save(Card o) {
        boolean result = true;
        try {
            Session session = HibernateUtil.getSessionFactory().getCurrentSession();
            session.beginTransaction();

            session.save(o);

            session.flush();

            session.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }
    
    /****** OTHERS ******/
    
    public static boolean areCardsLoaded()
    {
        return getCards().size() > 0;
    }
    
    private static List executeQuery(String query) {
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();

        List answer = session.createQuery(query).list();
        session.getTransaction().commit();
        return answer;
    }
}
